package com.younge.spring.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.younge.spring.api.param.UserLoginParam;
import com.younge.spring.api.result.MenuListResult;
import com.younge.spring.api.result.UserInfoResult;
import com.younge.spring.api.result.UserLoginResult;
import com.younge.spring.component.security.SecurityProperties;
import com.younge.spring.repository.SysUserRepository;
import com.younge.spring.repository.dao.SysUser;
import com.younge.spring.service.SysMenuService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping(path = "/web")
@Slf4j
public class AuthController {

    private final StringRedisTemplate redis;
    private final SecurityProperties securityProperties;
    private final SysUserRepository sysUserRepository;
    private final SysMenuService sysMenuService;
    private final ObjectMapper mapper;

    public AuthController(StringRedisTemplate redis, SecurityProperties securityProperties,
                          SysUserRepository sysUserRepository, SysMenuService sysMenuRepository, ObjectMapper mapper) {
        this.redis = redis;
        this.securityProperties = securityProperties;
        this.sysUserRepository = sysUserRepository;
        this.sysMenuService = sysMenuRepository;
        this.mapper = mapper;
    }

    @PostMapping("/auth/login")
    public Map<String, String> login(@RequestBody UserLoginParam userLoginParam) throws JsonProcessingException {
        // 1. 验证用户名和密码
        Optional<SysUser> sysUserOpt = sysUserRepository.findByUsernameAndPassword(userLoginParam.getUsername(),
                userLoginParam.getPassword());
        SysUser sysUser = sysUserOpt.orElseThrow(() -> new RuntimeException("用户名或密码错误"));
        // 2. 生成随机 Token
        String token = UUID.randomUUID().toString();

        // 3. 存 Redis（key = token，value = 精简用户信息）
        redis.opsForValue().set("token:" + token, mapper.writeValueAsString(sysUser),
                Duration.ofMinutes(securityProperties.getJwt().getTtl()));

        UserLoginResult result = new UserLoginResult(token, "", securityProperties.getJwt().getTtl(), token);

        return Map.of("accessToken", token);
    }

    @GetMapping("/user/info")
    public UserInfoResult UserInfo() {
        UsernamePasswordAuthenticationToken auth =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        if (auth != null && auth.isAuthenticated()) {
            SysUser principal = (SysUser) auth.getPrincipal();  // 通常为 UserDetails
            Collection<? extends GrantedAuthority> roles = auth.getAuthorities(); // 角色/权限
            UserInfoResult userInfo = new UserInfoResult(principal.getUsername(),
                    roles.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
            try {
                log.debug(mapper.writeValueAsString(userInfo));
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
            return userInfo;
        }
        return null;
    }

    @GetMapping("/auth/codes")
    public String AuthCodes(HttpServletRequest request) throws JsonProcessingException {
        return "";
    }

    @GetMapping("/auth/logout")
    public String UserLogout(HttpServletRequest request) throws JsonProcessingException {
        String token = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (StringUtils.hasLength(token)) {
            if (token.startsWith("Bearer")) {
                token = "token:" + token.substring(7);
            } else {
                token = "token:" + token;
            }
            redis.delete(token);
        }
        return "用户已登出";
    }

    @GetMapping("/menu/all")
    public List<MenuListResult> getMenuList() throws JsonProcessingException {
        return sysMenuService.getMenuList("1", true);
    }
}
